package com.competition.web.admin.service.upload.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;
import com.common.util.FileFormatVerifyUtil;
import com.common.util.FileType;
import com.common.util.RandomString;
import com.competition.web.admin.config.OssConfig;
import com.competition.web.admin.service.IUploadService;
import com.msg.ResponseCode;
import com.returns.value.CodeAndData;
import com.returns.value.ICodeAndData;

@Service
public class FileServiceImpl implements IUploadService {

	private OssConfig ossConfig;

	@Autowired
	public void setOssConfig(OssConfig ossConfig) {
		this.ossConfig = ossConfig;
	}

	@Override
	public <V> ICodeAndData<String> uploadFileToOSS(InputStream inputStream, String fileName,
			Function<V, String> function, long totalSize) {

		// 验证后缀
		String suffix = fileName.substring(fileName.indexOf('.'));

		if (null == FileType.getImageType().get(suffix)) {
			return new CodeAndData<String>(ResponseCode.ERROR_FILE_TYPE, null);
		}

		// 验证大小

		if (totalSize > this.ossConfig.getSize()) {
			return new CodeAndData<String>(ResponseCode.FILE_ALREADY_MAX, null);
		}

		try {
			// 验证二进制
			byte[] b = new byte[16];

			inputStream.read(b);

			boolean pass = FileFormatVerifyUtil.suffixVerify(b, suffix);
//					
			if (false == pass) {
				return new CodeAndData<String>(ResponseCode.ERROR_BINARY_FILE_TYPE, null);
			}

			// 获取文件名称

			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

			Date date = new Date();

			String perfix = function.apply((V) ossConfig);

			RandomString randomString = new RandomString(5);

			fileName = sdf.format(date) + "-" + randomString.getString() + suffix;

			String dir = perfix + sdf.format(date);

			String rootPath = this.ossConfig.getRootpath();

			File dirF = new File(rootPath + dir);

			if (!dirF.isDirectory()) {
				dirF.mkdirs();
			}

			String tempPath = this.getTmpPath(inputStream);

			inputStream.close();

			File file = new File(tempPath);

			String output = rootPath + dir + "/" + fileName;

			boolean res = file.renameTo(new File(output));

			if (false == res) {
				return new CodeAndData<String>(ResponseCode.ERROR_MOVE_FILE, null);
			}

			return new CodeAndData<String>(ResponseCode.SUCCESS,
					this.ossConfig.getLocalPicURL() + dir + "/" + fileName);

		} catch (Exception e) {

			e.printStackTrace();

		}
		return new CodeAndData<String>(ResponseCode.ERROR, null);
	}

	private String getTmpPath(InputStream inputStream) throws Exception {

		Field pathField = inputStream.getClass().getDeclaredField("path");

		pathField.setAccessible(true);

		return pathField.get(inputStream).toString();
	}

	protected ICodeAndData<String> checkFile(InputStream inputStream, String fileName, long totalSize)
			throws IOException {

		// 验证后缀
		String suffix = fileName.substring(fileName.lastIndexOf('.'));

		if (null == FileType.getImageType().get(suffix)) {
			return new CodeAndData<String>(ResponseCode.ERROR_FILE_TYPE, null);
		}

		// 验证大小

		if (totalSize > this.ossConfig.getSize()) {
			return new CodeAndData<String>(ResponseCode.FILE_ALREADY_MAX, null);
		}

		// 验证二进制
		byte[] b = new byte[16];

		inputStream.read(b);

		boolean pass = FileFormatVerifyUtil.suffixVerify(b, suffix);
//							
		if (false == pass) {
			return new CodeAndData<String>(ResponseCode.ERROR_BINARY_FILE_TYPE, null);
		}

		return new CodeAndData<String>(ResponseCode.SUCCESS, "");

	}

	@Override
	public <V> ICodeAndData<String> parseXlxs(InputStream inputStreamSource, String fileName, long totalSize) {

		try {

			ICodeAndData<String> codeAndData = this.checkFile(inputStreamSource, fileName, totalSize);

			codeAndData.setData(getTmpPath(inputStreamSource));

			return codeAndData;

		} catch (Exception e) {
			throw new Error(e);
		} finally {
			try {
				inputStreamSource.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}